package danceserver;

import com.rapplogic.xbee.api.ApiId;
import com.rapplogic.xbee.api.XBee;
import com.rapplogic.xbee.api.XBeeAddress64;
import com.rapplogic.xbee.api.XBeeException;
import com.rapplogic.xbee.api.XBeeResponse;
import com.rapplogic.xbee.api.XBeeTimeoutException;
import com.rapplogic.xbee.api.zigbee.ZNetRemoteAtRequest;
import com.rapplogic.xbee.api.zigbee.ZNetRemoteAtResponse;
import com.rapplogic.xbee.api.zigbee.ZNetRxIoSampleResponse;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author 0
 */
public class Model implements Runnable {

    XBee xbee;
    XBeeAddress64 remoteAddress;
    ZNetRemoteAtRequest request;
    long time;
    boolean D3;
    Controller _controller;

    public Model(Controller c) {
        _controller = c;
        time = System.currentTimeMillis();

    }

    public void reset() {
        time = System.currentTimeMillis();
        D3 = true;

        try {
            if (xbee != null) {
                xbee.close();
            }
            xbee = new XBee();
            xbee.open("COM3", 57600);
            startServer();
        } catch (XBeeException ex) {
            Logger.getLogger(Model.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void startServer() {

        while (true) {
            try {

                XBeeResponse response = xbee.getResponse();


                if (response.getApiId() == ApiId.ZNET_IO_SAMPLE_RESPONSE) {
                    if (response.getClass().toString().equals("class com.rapplogic.xbee.api.zigbee.ZNetRxIoSampleResponse")) {

                        ZNetRxIoSampleResponse ioSample = (ZNetRxIoSampleResponse) response;
                        //System.out.println("Received a sample from " + ioSample.getRemoteAddress64());

                        double mainVoltage = getVoltage(ioSample.getSupplyVoltage());
                        double vRef = (mainVoltage / 3.3) * 100;

                        System.out.println("supply voltage: " + mainVoltage);
                        
                        Vector<Integer> readings = new Vector<Integer>();
                        int xr = (int) getAnalogVoltage(ioSample.getAnalog2(), mainVoltage);
                        //System.out.println("Analog D0 (pin 20) 10-bit reading is " + xr);
                        readings.add(xr);

                        int yr = (int) getAnalogVoltage(ioSample.getAnalog0(), mainVoltage);
                        //System.out.println("Analog D1 (pin 19) 10-bit reading is " + yr);
                        readings.add(yr);

                        int zr = (int) getAnalogVoltage(ioSample.getAnalog1(), mainVoltage);
                        //System.out.println("Analog D2 (pin 18) 10-bit reading is " + zr);
                        readings.add(zr);

                        //System.out.println("time: " + (System.currentTimeMillis() - time));
                        time = System.currentTimeMillis();
                        _controller.setValues(readings, time);
                    } else {
                        reset();
                    }
                    //System.out.println("Digital D4 (pin 11) is " + (ioSample.isD4On() ? "on" : "off"));
                }
            } catch (XBeeException ex) {
                //Logger.getLogger(Model.class.getName()).log(Level.SEVERE, null, ex);
                System.out.println("error: need to reset here");
                reset();
            } catch (ClassCastException ex) {
                reset();
                System.out.println("class cast exception");
            }
        }
    }

    public static double getVoltage(int reading) {
        double percent = (double) reading / 1024;
        double deltaV = percent * .9;
        double voltage = 2.7 + deltaV;
        return voltage;
    }

    public int getAnalogVoltage(int reading, double vRef) {

        double ratio = (double) reading / 1024;

        double volts = ratio * 1.2;

        double percent = volts / (vRef * .32);
        percent = percent * 100;
        

        return (int) percent;

    }

    public void action(String effect) {


        if (effect.equals("Exit")) {
            System.exit(0);
        }
        if (effect.equals("2g/6g")) {
            try {
                // replace with SH + SL of your end device
                XBeeAddress64 addr64 = new XBeeAddress64(0, 0x13, 0xa2, 0, 0x40, 0x3a, 0xb7, 0x1e);
                // turn on end device (pin 20) D0 (Digital output high = 5)
                ZNetRemoteAtRequest iorequest;
                if (D3) {

                    iorequest = new ZNetRemoteAtRequest(addr64, "D3", new int[]{5});
                    D3 = !D3;

                } else {

                    iorequest = new ZNetRemoteAtRequest(addr64, "D3", new int[]{0});
                    D3 = !D3;
                }
                ZNetRemoteAtResponse ioresponse = (ZNetRemoteAtResponse) xbee.sendSynchronous(iorequest, 10000);
                if (ioresponse.isOk()) {
                    System.out.println("successfully turned on pin 20 (D0)");
                } else {
                    throw new RuntimeException("failed to turn on pin 20.  status is " + ioresponse.getStatus());
                }
            } catch (XBeeTimeoutException ex) {
                // Logger.getLogger(Model.class.getName()).log(Level.SEVERE, null, ex);
            } catch (XBeeException ex) {
                //Logger.getLogger(Model.class.getName()).log(Level.SEVERE, null, ex);
            }
        }


    }

    public void run() {
        reset();
    }
}
